#!user/bin/env python3
# -- coding: utf-8 --
# 面向对象  【三大特性】
"""
1、封装：
a.将属性和方法书写到类的里面的操作即为封装
b.封装可以为属性和方法添加私有权限
2、继承
a.子类默认继承父类的所有属性和方法
b.子类可以重写父类属性和方法
3、多态
传入不同的对象，产生不同的结果
"""
"""
多态：调用不同子类对象的相同父类方法。
步骤：
（1）定义父类，并提供公共方法
（2）定义子类，并重写父类方法
（3）传递子类对象给调用者，可以看到不同子类执行效果不同
"""


class 复仇者联盟(object):  # 定义父类，并提供公共方法
    def 实例方法(self):
        print('打灭霸')


class 钢铁侠(复仇者联盟):  # 定义子类，并重写父类方法
    def 实例方法(self):
        print('空中作战')


class 美国队长(复仇者联盟):  # 定义子类，并重写父类方法
    def 实例方法(self):
        print('地面作战')


# 传入不同的对象，执行不同的代码，即不同的实例方法函数
class 神盾局(object):
    def 指挥_实例方法(self, 复仇者联盟):
        复仇者联盟.实例方法()


空军 = 钢铁侠()
陆军 = 美国队长()
指挥官 = 神盾局()
指挥官.指挥_实例方法(空军)
指挥官.指挥_实例方法(陆军)
print(''.center(30, '='))

# 面向对象  【类属性和实例属性】
"""
a.类属性就是类对象所拥有的属性，它被该类的所有实例对象所共有。
b.类属性可以使用 类对象 或 实例对象 访问。
类属性优点：
a.记录的某项数据始终保持一致不发生变化时使用。
b.实例属性要求每个对象为其单独开辟一份内存空间来记录数据，而类属性为全类所区有，仅占用一份内存，更加节省内存空间。
"""


class 类(object):
    name = '张三'  # 和类关联在一起的变量叫类变量,也叫类属性
    age = '20'


print(类.name)  # 类对象访问
对象1 = 类()  # 实例对象 访问
print(对象1.age)
print(''.center(30, '='))
"""
类属性只能通过类对象修改，不能通过实例对象修改，如果通过实例对象修改类属性，虽然语法没有报错，但是并没有修改类对象，而是创建了一个实例属性。
"""


class 类(object):
    name = '张三'  # 和类关联在一起的变量叫类变量,也叫类属性
    age = '20'


对象1 = 类()
对象2 = 类()
# 通过类对象修改类属性
# 类.name='李四'
# 通过实例对象修改类属性
对象1.name = '李四'

print(类.name)
print(对象1.name)
print(对象2.name)
print(''.center(30, '='))

# 面向对象  【类方法】
"""
类方法特点：需要用装饰器@classmethod来标识其为类方法，对于类方法，第一个参数必需是类对象。一般以cls作为第一个参数。
使用场景
（1）当方法中 需要使用类对象（如访问私有类属性等）时，定义类方法
（2）类方法一般和类属性配合使用
"""


class 李小龙(object):  # 1.定义类
    __功夫 = '使用截拳道'  # 私有属性，类方法获取私有属性

    # 定义类方法
    @classmethod
    def get_功夫(cls):
        return cls.__功夫


# 创建对象，调用类方法
徒弟1 = 李小龙()
print(徒弟1.get_功夫())
print(''.center(30, '='))
# 类的方法按照调用方式可以分为3种：实例方法,类方法,静态方法
"""
（1）实例方法：只能通过实例对象调用，不能通过类进行调用，定义时使用self关键字，self代表实例对象本身。
（2）类方法：可以被类调用，也可被实例对象调用，实例调用可以给类增加属性，类的属性修改需要通过类进行修改，类方法需要使用关键字cls，定义时需要在函数前加@classmethod
（3）静态方法：可以使用实例对象调用，也可以使用类进行调用，他的特点是没有参数限制，定义时需要在函数前加@staticmethod
"""
# 面向对象  【静态方法】
"""
静态方法：
a.需要通过装饰器 @staticmethod 来进行修饰，静态方法既不需要传递类对象也不需要传递实例对象（形参没有self/cls）
b.静态方法 也能够通过 实例对象 和 类对象 去访问。 
使用场景：
（1）当方法中 既不需要使用实例对象（如实例对象，实例属性），也不需要使用类对象（如类属性、类方法、创建实例等）时，定义静态方法。
（2）取消不需要的参数传递，有利于 减少不必要的内存占用和性能消耗
"""


class 叶问(object):
    @staticmethod
    def 功夫():
        print('使用咏春拳')


# 类调用
叶问.功夫()
# 实例对象调用
李小龙 = 叶问()
李小龙.功夫()
print(''.center(30, '='))

# 面向对象  【静态属性】
"""
静态属性：@property
作用：把类的函数属性，封装成类似数据属性，再调用函数时，必须不带（）执行
"""


class 成龙(object):
    @property
    def 静态属性(self):
        print('这是定义的静态属性')


# 调用
# 成龙.静态属性
陈祖明 = 成龙()
陈祖明.静态属性  # 再调用函数时，必须不带（）执行
